package com.core.websocket;

import com.core.dto.SocketUserDTO;
import com.core.model.lxf.SocketUser;
import com.core.shared.DataToJson;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.util.*;

/**
 * Created with IntelliJ IDEA.
 * User: xianfei
 * Date: 15-7-29
 * Time: 上午10:02
 * To change this template use File | Settings | File Templates.
 */

@ServerEndpoint(value = "/ws3/{username}")
public class WebSocket {        //正常使用

    private static Map<String, SocketUser> userMap = new Hashtable<>();

    @OnOpen
    public void onOpen(Session session, @PathParam("username") String username) throws UnsupportedEncodingException {
        username = new String(username.getBytes("iso-8859-1"), "utf-8");
        SocketUser socketUser;
        broadcastAll(username, "加入了聊天室!");
        try {
            InetAddress inetAddress = InetAddress.getLocalHost();
            String ip = inetAddress.getHostAddress();
            String canonicalHostName = inetAddress.getCanonicalHostName();
            String hostName = inetAddress.getHostName();
            socketUser = new SocketUser(session, username, ip);
            userMap.put(session.getId(), socketUser);
            String text = ip + ", " + hostName + ", " + username + ",聊天室欢迎您!!!" + canonicalHostName;
            session.getBasicRemote().sendText(text);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @OnMessage
    public void onMessage(String unscrambledWord, Session session) {
        String[] messageType = unscrambledWord.split("&");
        if ("all".equals(messageType[0])) {
            broadcastAll(userMap.get(session.getId()).username(), messageType[1]);
        } else {
            broadcast(userMap.get(session.getId()).username(), messageType[1], messageType[0]);
        }
    }

    /**
     * 广播给所有人
     *
     * @param message
     */
    public static void broadcastAll(String username, String message) {
        Set<Map.Entry<String, SocketUser>> set = userMap.entrySet();
        for (Map.Entry<String, SocketUser> i : set) {
            try {
                i.getValue().session().getBasicRemote().sendText(username + ":" + message);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public static void broadcast(String username, String message, String sessionId) {
        Session session = userMap.get(sessionId).session();
        try {
            session.getBasicRemote().sendText("[私聊] " + username + " 悄悄对我说:" + message);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @OnClose
    public void onClose(Session session, CloseReason closeReason) {
        userMap.remove(session.getId());
        System.out.println(String.format("Session %s closed because of %s", session.getId(), closeReason));
    }

    @OnError
    public void error(Session session, java.lang.Throwable throwable) {
        userMap.remove(session.getId());
        System.out.println("session " + session.getId() + " error:" + throwable);
    }

    public static String getAllUserIp() {
        StringBuilder s = new StringBuilder();
        for (Map.Entry<String, SocketUser> entry : userMap.entrySet()) {
            s.append(entry.getValue().userIp()).append("<br/>");
        }
        return s.toString();
    }

    public static void findAllOnlineUser(HttpServletResponse response) {
        List<SocketUser> socketUsers = new ArrayList<>();
        for (Map.Entry<String, SocketUser> entry : userMap.entrySet()) {
//            if (!entry.getValue().session().getId().equals(session.getId())) {
            socketUsers.add(entry.getValue());
//            }
        }
        List<SocketUserDTO> socketUserDTOs = SocketUserDTO.toDTOs(socketUsers);
        DataToJson.socketUserToJson(socketUserDTOs, response);
    }

    public static String getIpAddress(HttpServletRequest request) {
        if (hasProxy(request)) {
            String ip = null;
            boolean proxyHeadHasIp = false;
            for (int i = 0; i < PROXY_HEAD_TAGS.length; i++) {
                ip = request.getHeader(PROXY_HEAD_TAGS[i]);
                if (!isNull(ip)) {
                    proxyHeadHasIp = true;
                    break;
                }
            }
            if (!proxyHeadHasIp) {
                ip = request.getRemoteAddr();
            }
            if (ip != null && ip.length() > 0) {
                String[] tempIps = ip.split(",");
                if (tempIps != null && tempIps.length > 1) {
                    ip = tempIps[0];
                }
            }
            return ip;
        } else {
            return request.getRemoteAddr();
        }

    }

    private static boolean isNull(String ip) {
        // 有些是unknown，为有些可能是其他的比如unknown.unknown.
        // 严格来讲，需要判断ip地址是否是数字加点号。

        // 有些使用了反向代理后，会显示本机的127.0.0.1
        // 严格来讲，需要判断ip是否是保留的ip地址。
        return ip == null || ip.trim().length() == 0 || ip.indexOf("u") != -1 || ip == "127.0.0.1";
    }

    private static boolean hasProxy(HttpServletRequest request) {
        for (int i = 0; i < PROXY_HEAD_TAGS.length; i++) {
            if (request.getHeader(PROXY_HEAD_TAGS[i]) != null) {
                return true;
            }
        }
        return false;
    }

    private static String[] PROXY_HEAD_TAGS = {"X-Forwarded-For", "Proxy-Client-IP", "WL-Proxy-Client-IP", "HTTP_CLIENT_IP", "HTTP_X_FORWARDED_FOR", "ORIG_CLIENT_IP"};

}
